package com.jintian.smart.kernel.web.listener;

import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.URLUtil;
import com.jintian.smart.kernel.common.util.SmartEnumUtil;
import com.jintian.smart.kernel.core.code.ErrorCodeRegister;
import com.jintian.smart.kernel.core.enumeration.SystemEnvironmentEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.web.context.WebServerApplicationContext;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;

/**
 * 启动监听器
 */
@Slf4j
@Component
@Order(value = 1024)
public class WebServerListener implements ApplicationListener<WebServerInitializedEvent> {
    @Value(value = "${smart.debug.controller: false}")
    private Boolean printController;
    @Value(value = "${smart.debug.beandefination: false}")
    private Boolean printBeanDefinition;

    @Override
    public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
        WebServerApplicationContext context = webServerInitializedEvent.getApplicationContext();
        // 初始化reload
        initReload(context);
        // 打印所有控制器
        if (printController) {
            showAllControllers(context);
        }
        // 打印所有BeanDefinition
        if (printBeanDefinition) {
            showAllBeanDefinitions(context);
        }
        // 项目信息
        showProjectMessage(webServerInitializedEvent);
    }

    /**
     * 显示项目信息
     */
    private void showProjectMessage(WebServerInitializedEvent webServerInitializedEvent) {
        WebServerApplicationContext context = webServerInitializedEvent.getApplicationContext();
        Environment env = context.getEnvironment();

        //获取服务信息
        String ip = NetUtil.getLocalhost().getHostAddress();
        Integer port = webServerInitializedEvent.getWebServer().getPort();
        String contextPath = env.getProperty("server.servlet.context-path");
        if (contextPath == null) {
            contextPath = "";
        }
        String profile = env.getProperty("spring.profiles.active");
        SystemEnvironmentEnum environmentEnum = SmartEnumUtil.getEnumByValue(profile, SystemEnvironmentEnum.class);
        String projectName = env.getProperty("project.name");
        //拼接服务地址
        String title = String.format("\u001B[32m-------------【%s】 服务已成功启动 （%s started successfully）-------------", projectName, projectName);

        // 初始化状态码
        int codeCount = ErrorCodeRegister.initialize();
        String localhostUrl = URLUtil.normalize(String.format("http://localhost:%d%s", port, contextPath), false, true);
        String externalUrl = URLUtil.normalize(String.format("http://%s:%d%s", ip, port, contextPath), false, true);
        String swaggerUrl = URLUtil.normalize(String.format("http://localhost:%d%s/swagger-ui/index.html", port, contextPath), false, true);
        String knife4jUrl = URLUtil.normalize(String.format("http://localhost:%d%s/doc.html", port, contextPath), false, true);
        log.warn("\n{}\n" +
                        "\t当前启动环境:\t{} , {}" +
                        "\n\t返回码初始化:\t完成{}个返回码初始化" +
                        "\n\t服务本机地址:\t{}" +
                        "\n\t服务外网地址:\t{}" +
                        "\n\tSwagger地址:\t{}" +
                        "\n\tknife4j地址:\t{}" +
                        "\n-----------------------------------------------------------------------------------------------\n\u001B[32m",
                title, profile, environmentEnum.getDesc(), codeCount, localhostUrl, externalUrl, swaggerUrl, knife4jUrl);
    }

    /**
     * 显示所有控制器
     */
    private void showAllControllers(WebServerApplicationContext context) {
        RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();

        List<String> controllerInfoList = new ArrayList<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
            RequestMappingInfo requestMappingInfo = entry.getKey();
            HandlerMethod handlerMethod = entry.getValue();

            Set<String> patterns = requestMappingInfo.getPatternValues();
            String controllerName = handlerMethod.getBeanType().getSimpleName();
            String methodName = handlerMethod.getMethod().getName();

            for (String pattern : patterns) {
                controllerInfoList.add(String.format("\t%s \t\t%s.%s", pattern, controllerName, methodName));
            }
        }

        Collections.sort(controllerInfoList);

        log.warn("\u001B[32m\n=====================【所有控制器接口】=====================\n\u001B[0m {} \u001B[32m\n============================================\n\u001B[0m",
                String.join("\n", controllerInfoList));
    }

    /**
     * 显示所有BeanDefinition
     */
    private void showAllBeanDefinitions(WebServerApplicationContext context) {
        ConfigurableApplicationContext configurableContext = (ConfigurableApplicationContext) context;
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableContext.getBeanFactory();
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();

        log.warn("\u001B[32m\n=====================【所有BeanDefinitions】共{}个=====================\u001B[0m", beanDefinitionNames.length);

        List<String> beanDefinitionInfoList = new ArrayList<>();
        for (String beanName : beanDefinitionNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            String className = beanDefinition.getBeanClassName();
            if (className == null) {
                // 处理FactoryBean等特殊情况
                className = beanDefinition.getFactoryBeanName() != null ? "[FactoryBean] " + beanDefinition.getFactoryBeanName() : "[Unknown]";
            }
            beanDefinitionInfoList.add(String.format("\t%s \t\t-> %s", beanName, className));
        }

        // 排序
        Collections.sort(beanDefinitionInfoList);

        // 打印
        for (String beanDefinitionInfo : beanDefinitionInfoList) {
            log.warn(beanDefinitionInfo);
        }
        log.warn("\u001B[32m\n==================================================================\u001B[0m");
    }

    /**
     * 初始化reload
     */
    private void initReload(WebServerApplicationContext applicationContext) {
//        //将applicationContext转换为ConfigurableApplicationContext
//        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
//
//
//        //获取BeanFactory
//        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();
//
//        //动态注册bean
//        SmartReloadManager reloadManager = new SmartReloadManager(applicationContext.getBean(ReloadCommand.class), intervalSeconds);
//        defaultListableBeanFactory.registerSingleton("smartReloadManager", reloadManager);
    }
}